package cn.good.yan.sf.t3;

import java.util.Iterator;
import java.util.function.Consumer;

/**
 * 3.链表 - 自定义 链表 - 带哨兵  null 1  2  3
 * a 添加头节点（头插法） - addFirst（）
 * b 遍历 （有4种方式）
 * c 添加尾节点 （尾插法） - addLast（）
 * d 根据下标获取单条数据 - getIndex
 * e 根据索引添加数据 - addIndex
 * f 删除头元素 - removeFirst
 * g 删除指定元素 - （根据下标指定删除元素） - remove
 *
 * @author shengren.yan
 * @create 2024-05-01
 */
public class Demo2 implements Iterable<Integer> {

    private static class Node {
        private int value; //值
        private Node next; //下一个节点

        public Node(int value, Node next) {
            this.value = value;
            this.next = next;
        }
    }

    // 头节点
    private Node head = new Node(-11, null);

    // a 添加头节点（头插法） - addFirst（）
    public void addFirst(int element) {
//        head.next = new Node(element, head.next);
        // 添加0 - 相当于添加下标0的元素  - 等价于上面的
        addIndex(0, element);
    }

    // b 遍历 （有1种方式）
    public void loop1() {
        Node n;
        for (n = head.next; n != null; n = n.next) {
            System.out.println(n.value);
        }
    }

    // b 遍历 （有2种方式）
    public void loop2(Consumer<Integer> consumer) {
        Node n;
        for (n = head.next; n != null; n = n.next) {
//            System.out.println(n.value);
            consumer.accept(n.value);
        }
    }

    // b 遍历 （有3种方式）
    public void loop3() {
        Node n = head.next;
        while (n != null) {
            System.out.println(n.value);
            n = n.next;
        }
    }

    // b 遍历 （有4种方式） - 递归
    public void loop4() {
        re(head.next);
    }

    private void re(Node node) {
        if (node == null) {
            return;
        }
        System.out.println(node.value);
        node = node.next;
        re(node); // 递归
    }

    // b 遍历 （有4种方式）
    @Override
    public Iterator<Integer> iterator() {
        return new Iterator<Integer>() {
            Node n = head.next;

            @Override
            public boolean hasNext() {
                return n != null;
            }

            @Override
            public Integer next() {
                int value = n.value;
                n = n.next;
                return value;
            }
        };
    }

    //  c 添加尾节点 （尾插法） - addLast（）
    public void addLast(int element) {
        Node lastNode = getLastNode();
        // 因为有哨兵，最后一个节点，最次也是哨兵，不会是空，少了空指针判断
        lastNode.next = new Node(element, null);
    }

    // 获取最后一个节点
    private Node getLastNode() {
        Node n;
        for (n = head; n.next != null; n = n.next) {

        }
        return n;
    }

    //  d 根据下标获取单条数据 - getIndex
    public int getIndex(int index) {
        Node node = getNode(index);
        if (node == null || node == head) {
            System.out.println("下标越界");
            return -1;
        }
        return node.value;
    }

    // 根据下标获取元素
    private Node getNode(int index) {
        Node n;
        int i = -1;
        for (n = head; n != null; n = n.next) {
            //            System.out.println(n.value + " - " + i);
            if (index == i) {
                return n;
            }
            i++;
        }
        return null;
    }

    // e 根据索引添加数据 - addIndex
    public void addIndex(int index, int element) {
        Node prev = getNode(index - 1);
        if (prev == null) {
            System.out.println("下标越界");
            return;
        }
        prev.next = new Node(element, prev.next);
    }

    // f 删除头元素 - removeFirst
    public void removeFirst() {
//        Node next = head.next;
//        if (next == null) {
//            System.out.println("下标越界");
//            return;
//        }
//        head.next = next.next;
        // 删除0 - 相当于删除下标0的元素，等价于
        remove(0);
    }

    // g 删除指定元素 - （根据下标指定删除元素） - remove
    public void remove(int index) {
        Node prev = getNode(index - 1);
        if (prev == null) {
            System.out.println("下标越界");
            return;
        }
        Node next = prev.next;
        if (next == null) {
            System.out.println("下标越界");
            return;
        }
        prev.next = next.next;
    }

    public static void main(String[] args) {
        Demo2 d = new Demo2();
        // 测试  a 添加头节点（头插法） - addFirst（）
//        d.addFirst(1);
//        d.addFirst(2);
//        d.addFirst(3);
//        System.out.println(d);
        // 测试 b 遍历
//        d.loop1();
//        d.loop2(x -> {
//            System.out.println(x);
//        });
//        d.loop3();
//        d.loop4();
//        for (Integer e : d) {
//            System.out.println(e);
//        }
//     测试 c 添加尾节点 （尾插法） - addLast（）
//        d.addFirst(1);
//        d.addFirst(2);
//        d.addFirst(3);
//        System.out.println(d);

        // 测试 d 根据下标获取单条数据 - getIndex
//        System.out.println(d.getIndex(-1));
//        System.out.println(d.getIndex(0));
//        System.out.println(d.getIndex(1));
//        System.out.println(d.getIndex(5));

        // 测试 e 根据索引添加数据 - addIndex
//        d.addIndex(-1, 1);
//        d.addIndex(0, 1);
//        d.addIndex(1, 2);
//        d.addIndex(3, 20);
//        System.out.println(d);

        // 测试 f 删除头元素 - removeFirst
        d.addLast(1);
        d.addLast(2);
        d.addLast(3);
//        d.removeFirst();
        System.out.println(d);
        // 测试 g 删除指定元素 - （根据下标指定删除元素） - remove
//        d.remove(0);
//        d.remove(-1);
        d.remove(6);
        System.out.println(d);

    }

}
